home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_068 / mg1b / buffer.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  14KB  |  557 lines

  1. /*
  2.  *        Buffer handling.
  3.  */
  4. #include    "def.h"
  5.  
  6. static    itor();
  7.  
  8. /*
  9.  * Attach a buffer to a window. The
  10.  * values of dot and mark come from the buffer
  11.  * if the use count is 0. Otherwise, they come
  12.  * from some other window.
  13.  */
  14. /*ARGSUSED*/
  15. usebuffer(f, n, k) {
  16.     register BUFFER    *bp;
  17.     register int    s;
  18.     char        bufn[NBUFN];
  19.  
  20.     /* Get buffer to use from user */
  21.     if (curbp->b_altb != NULL)
  22.         s=eread("Switch to buffer: (default %s) ", bufn, NBUFN,
  23.              EFNEW|EFBUF, 
  24. #ifdef    VARARGS
  25.              curbp->b_altb->b_bname
  26. #else
  27.              &(curbp->b_altb->b_bname), (char *) NULL
  28. #endif
  29.              ) ;
  30.     else
  31.         s=eread("Switch to buffer: ", bufn, NBUFN, EFNEW|EFBUF
  32. #ifndef VARARGS
  33.              ,(char *) NULL
  34. #endif
  35.              );
  36.     if (s == ABORT) return (s);
  37.     if (s == FALSE && curbp->b_altb != NULL) bp = curbp->b_altb ;
  38.     else if ((bp=bfind(bufn, TRUE)) == NULL) return (FALSE);
  39.  
  40.     /* and put it in current window */
  41.     curbp = bp;
  42.     return showbuffer(bp, curwp, WFFORCE|WFHARD);
  43. }
  44.  
  45. /*
  46.  * pop to buffer asked for by the user.
  47.  */
  48. /*ARGSUSED*/
  49. poptobuffer(f, n, k) {
  50.     register BUFFER    *bp;
  51.     register WINDOW    *wp;
  52.     register int    s;
  53.     char        bufn[NBUFN];
  54.     WINDOW        *popbuf();
  55.  
  56.     /* Get buffer to use from user */
  57.     if (curbp->b_altb != NULL)
  58.         s=eread("Switch to buffer in other window: (default %s) ",
  59.              bufn, NBUFN, EFNEW|EFBUF, 
  60. #ifdef    VARARGS
  61.              curbp->b_altb->b_bname
  62. #else
  63.              &(curbp->b_altb->b_bname) ,(char *) NULL
  64. #endif
  65.              ) ;
  66.     else
  67.         s=eread("Switch to buffer in other window: ", bufn, NBUFN,
  68.         EFNEW|EFBUF
  69. #ifndef VARARGS
  70.         , (char *) NULL
  71. #endif
  72.         ) ;
  73.     if (s == ABORT) return (s);
  74.     if (s == FALSE && curbp->b_altb != NULL) bp = curbp->b_altb ;
  75.     else if ((bp=bfind(bufn, TRUE)) == NULL) return (FALSE);
  76.  
  77.     /* and put it in a new window */
  78.     if ((wp = popbuf(bp)) == NULL) return FALSE;
  79.     curbp = bp;
  80.     curwp = wp;
  81.     return TRUE;
  82. }
  83.  
  84. /*
  85.  * Dispose of a buffer, by name.
  86.  * Ask for the name. Look it up (don't get too
  87.  * upset if it isn't there at all!). Clear the buffer (ask
  88.  * if the buffer has been changed). Then free the header
  89.  * line and the buffer header. Bound to "C-X K".
  90.  */
  91. /*ARGSUSED*/
  92. killbuffer(f, n, k) {
  93.     register BUFFER    *bp;
  94.     register BUFFER    *bp1;
  95.     register BUFFER    *bp2;
  96.     WINDOW        *wp;
  97.     register int    s;
  98.     char        bufn[NBUFN];
  99.  
  100.     if ((s=eread("Kill buffer: (default %s) ", bufn, NBUFN, EFNEW|EFBUF,
  101. #ifdef    VARARGS
  102.             curbp->b_bname
  103. #else
  104.             &(curbp->b_bname)
  105. #endif
  106.             )) == ABORT) return (s);
  107.     else if (s == FALSE) bp = curbp ;
  108.     else if ((bp=bfind(bufn, FALSE)) == NULL) return FALSE;
  109.  
  110.     if (bp->b_nwnd != 0) {
  111.         if ((bp1 = bp->b_altb) == NULL) return FALSE;
  112.         if (bclear(bp) != TRUE) return TRUE;
  113.         for (wp = wheadp; bp->b_nwnd > 0; wp = wp->w_wndp) {
  114.             /* Special case - could use showbuf, but don't */
  115.             if (wp->w_bufp == bp) {
  116.                 --bp->b_nwnd;
  117.                 ++bp1->b_nwnd;
  118.                 wp->w_bufp  = bp1 ;
  119.                 wp->w_dotp  = bp1->b_dotp;
  120.                 wp->w_doto  = bp1->b_doto;
  121.                 wp->w_markp = bp1->b_markp;
  122.                 wp->w_marko = bp1->b_marko;
  123.                 wp->w_linep = bp1->b_linep;
  124.                 wp->w_flag |= WFMODE|WFFORCE|WFHARD;
  125.             }
  126.         }
  127.     }
  128.     else if (bclear(bp) != TRUE) return TRUE;
  129.     if (bp == curbp) curbp = bp->b_altb;
  130.     free((char *) bp->b_linep);        /* Release header line.    */
  131.     bp1 = NULL;                /* Find the header.    */
  132.     bp2 = bheadp;
  133.     while (bp2 != bp) {
  134.         if (bp2->b_altb == bp) 
  135.             bp2->b_altb = (bp->b_altb == bp2) ? NULL : bp->b_altb;
  136.         bp1 = bp2;
  137.         bp2 = bp2->b_bufp;
  138.     }
  139.     bp2 = bp2->b_bufp;            /* Next one in chain.    */
  140.     if (bp1 == NULL)            /* Unlink it.        */
  141.         bheadp = bp2;
  142.     else
  143.         bp1->b_bufp = bp2;
  144.     while (bp2 != NULL) {            /* Finish with altb's    */
  145.         if (bp2->b_altb == bp) 
  146.             bp2->b_altb = (bp->b_altb == bp2) ? NULL : bp->b_altb;
  147.         bp2 = bp2->b_bufp;
  148.     }
  149.     free(bp->b_bname);        /* Release name block    */
  150.     free((char *) bp);            /* Release buffer block    */
  151.     return (TRUE);
  152. }
  153.  
  154. /*
  155.  * Save some buffers - just call anycb with the arg flag.
  156.  */
  157. /*ARGSUSED*/
  158. savebuffers(f, n, k) {
  159.     if (anycb(f) == ABORT) return ABORT;
  160.     return TRUE;
  161. }
  162.  
  163. /*
  164.  * Display the buffer list. This is done
  165.  * in two parts. The "makelist" routine figures out
  166.  * the text, and puts it in a buffer. "popbuf"
  167.  * then pops the data onto the screen. Bound to
  168.  * "C-X C-B".
  169.  */
  170. /*ARGSUSED*/
  171. listbuffers(f, n, k) {
  172.     register BUFFER    *bp;
  173.     register WINDOW *wp;
  174.     BUFFER         *makelist();
  175.         WINDOW          *popbuf();
  176.  
  177.     if ((bp=makelist()) == NULL || (wp=popbuf(bp)) == NULL)
  178.         return FALSE;
  179.     wp->w_dotp = bp->b_dotp;    /* fix up if window already on screen */
  180.     wp->w_doto = bp->b_doto;
  181.     return TRUE;
  182. }
  183.  
  184. /*
  185.  * This routine rebuilds the text for the
  186.  * list buffers command. Return TRUE if
  187.  * everything works. Return FALSE if there
  188.  * is an error (if there is no memory).
  189.  */
  190. BUFFER *
  191. makelist() {
  192.     register char    *cp1;
  193.     register char    *cp2;
  194.     register int    c;
  195.     register BUFFER    *bp;
  196.     LINE        *lp;
  197.     register RSIZE    nbytes;
  198.     BUFFER        *blp;
  199.     char        b[6+1];
  200.     char        line[128];
  201.     
  202.     if ((blp = bfind("*Buffer List*", TRUE)) == NULL) return NULL;
  203.     if (bclear(blp) != TRUE) return NULL;
  204.     blp->b_flag &= ~BFCHG;            /* Blow away old.    */
  205.  
  206.     (VOID) strcpy(line, " MR Buffer");
  207.     cp1 = line + 10;
  208.     while(cp1 < line + 4 + NBUFN + 1) *cp1++ = ' ';
  209.     (VOID) strcpy(cp1, "Size   File");
  210.     if (addline(blp, line) == FALSE) return NULL;
  211.     (VOID) strcpy(line, " -- ------");
  212.     cp1 = line + 10;
  213.     while(cp1 < line + 4 + NBUFN + 1) *cp1++ = ' ';
  214.     (VOID) strcpy(cp1, "----   ----");
  215.     if (addline(blp, line) == FALSE) return NULL;
  216.     bp = bheadp;                /* For all buffers    */
  217.     while (bp != NULL) {
  218.         cp1 = &line[0];            /* Start at left edge    */
  219.         *cp1++ = (bp == curbp) ? '.' : ' ';
  220.         *cp1++ = ((bp->b_flag&BFCHG) != 0) ? '*' : ' ';
  221.         *cp1++ = ' ';            /* Gap.            */
  222.         *cp1++ = ' ';
  223.         cp2 = &bp->b_bname[0];        /* Buffer name        */
  224.         while ((c = *cp2++) != 0)
  225.             *cp1++ = c;
  226.         while (cp1 < &line[4+NBUFN+1])
  227.             *cp1++ = ' ';        
  228.         nbytes = 0;            /* Count bytes in buf.    */
  229.         if (bp != blp) {
  230.             lp = lforw(bp->b_linep);
  231.             while (lp != bp->b_linep) {
  232.                 nbytes += llength(lp)+1;
  233.                 lp = lforw(lp);
  234.             }
  235.         }
  236.         (VOID) itor(b, 6, nbytes);    /* 6 digit buffer size.    */
  237.         cp2 = &b[0];
  238.         while ((c = *cp2++) != 0)
  239.             *cp1++ = c;
  240.         *cp1++ = ' ';            /* Gap..            */
  241.         cp2 = &bp->b_fname[0];        /* File name        */
  242.         if (*cp2 != 0) {
  243.             while ((c = *cp2++) != 0) {
  244.                 if (cp1 < &line[128-1])
  245.                     *cp1++ = c;
  246.             }
  247.         }
  248.         *cp1 = 0;            /* Add to the buffer.    */
  249.         if (addline(blp, line) == FALSE)
  250.             return NULL;
  251.         bp = bp->b_bufp;
  252.     }
  253.     blp->b_dotp = lforw(blp->b_linep);    /* put dot at beginning of buffer */
  254.     blp->b_doto = 0;
  255.     return blp;                /* All done        */
  256. }
  257.  
  258. /*
  259.  * Used above.
  260.  */
  261. static itor(buf, width, num)
  262. register char buf[]; register int width; register RSIZE num; {
  263.     register RSIZE r;
  264.  
  265.     if (num / 10 == 0) {
  266.         buf[0] = (num % 10) + '0';
  267.         for (r = 1; r < width; buf[r++] = ' ')
  268.             ;
  269.         buf[width] = '\0';
  270.         return 1;
  271.     } else {
  272.         buf[r = itor(buf, width, num / (RSIZE)10)] = 
  273.                 (num % (RSIZE)10) + '0';
  274.         return r + 1;
  275.     }
  276.     /*NOTREACHED*/
  277. }
  278.  
  279. /*
  280.  * The argument "text" points to
  281.  * a string. Append this line to the
  282.  * buffer. Handcraft the EOL
  283.  * on the end. Return TRUE if it worked and
  284.  * FALSE if you ran out of room.
  285.  */
  286. addline(bp, text) register BUFFER *bp; char *text; {
  287.     register LINE    *lp;
  288.     register int    i;
  289.     register int    ntext;
  290.  
  291.     ntext = strlen(text);
  292.     if ((lp=lalloc((RSIZE) ntext)) == NULL)
  293.         return (FALSE);
  294.     for (i=0; i<ntext; ++i)
  295.         lputc(lp, i, text[i]);
  296.     bp->b_linep->l_bp->l_fp = lp;        /* Hook onto the end    */
  297.     lp->l_bp = bp->b_linep->l_bp;
  298.     bp->b_linep->l_bp = lp;
  299.     lp->l_fp = bp->b_linep;
  300.     if (bp->b_dotp == bp->b_linep)        /* If "." is at the end    */
  301.         bp->b_dotp = lp;        /* move it to new line    */
  302.     if (bp->b_markp == bp->b_linep)        /* ditto for mark     */
  303.         bp->b_markp = lp;
  304.     return (TRUE);
  305. }
  306.  
  307. /*
  308.  * Look through the list of buffers, giving the user
  309.  * a chance to save them.  Return TRUE if there are
  310.  * any changed buffers afterwards. Buffers that don't
  311.  * have an associated file don't count. Return FALSE
  312.  * if there are no changed buffers.
  313.  */
  314. anycb(f) {
  315.     register BUFFER    *bp;
  316.     register int    s = FALSE, save = FALSE;
  317.     char        prompt[NFILEN + 11];
  318.  
  319.     for (bp = bheadp; bp != NULL; bp = bp->b_bufp) {
  320.         if (*(bp->b_fname) != '\0'
  321.         &&  (bp->b_flag&BFCHG) != 0) {
  322.             (VOID) strcpy(prompt, "Save file ");
  323.             (VOID) strcpy(prompt + 10, bp->b_fname);
  324.             if ((f == TRUE || (save = eyorn(prompt)) == TRUE)
  325.             &&  writeout(bp, bp->b_fname) == TRUE) {
  326.                 bp->b_flag &= ~BFCHG;
  327.                 upmodes(bp);
  328.             } else s = TRUE;
  329.             if (save == ABORT) return (save);
  330.             save = TRUE;
  331.         }
  332.     }
  333.     if (save == FALSE && kbdmop == NULL)
  334.         ewprintf("(No files need saving)");
  335.     return s;
  336. }
  337.  
  338. /*
  339.  * Search for a buffer, by name.
  340.  * If not found, and the "cflag" is TRUE,
  341.  * create a buffer and put it in the list of
  342.  * all buffers. Return pointer to the BUFFER
  343.  * block for the buffer.
  344.  */
  345. BUFFER    *
  346. bfind(bname, cflag) register char *bname; {
  347.     register BUFFER    *bp;
  348.     char        *malloc();
  349.     register LINE    *lp;
  350.  
  351.     bp = bheadp;
  352.     while (bp != NULL) {
  353.         if (strcmp(bname, bp->b_bname) == 0)
  354.             return (bp);
  355.         bp = bp->b_bufp;
  356.     }
  357.     if (cflag!=TRUE) return NULL;
  358.     /*NOSTRICT*/
  359.     if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL) {
  360.         ewprintf("Can't get %d bytes", sizeof(BUFFER));
  361.         return NULL;
  362.     }
  363.     if ((bp->b_bname=malloc(strlen(bname)+1)) == NULL) {
  364.         ewprintf("Can't get %d bytes", strlen(bname)+1);
  365.         free((char *) bp);
  366.         return NULL;
  367.     }
  368.     if ((lp=lalloc((RSIZE) 0)) == NULL) {
  369.         free(bp->b_bname);
  370.         free((char *) bp);
  371.         return NULL;
  372.     }
  373.     bp->b_altb = bp->b_bufp  = NULL;
  374.     bp->b_dotp  = lp;
  375.     bp->b_doto  = 0;
  376.     bp->b_markp = NULL;
  377.     bp->b_marko = 0;
  378.     bp->b_flag  = 0;
  379.     bp->b_nwnd  = 0;
  380.     bp->b_linep = lp;
  381.     (VOID) strcpy(bp->b_fname, "");
  382.     (VOID) strcpy(bp->b_bname, bname);
  383.     lp->l_fp = lp;
  384.     lp->l_bp = lp;
  385.     bp->b_bufp = bheadp;
  386.     bheadp = bp;
  387.     return (bp);
  388. }
  389.  
  390. /*
  391.  * This routine blows away all of the text
  392.  * in a buffer. If the buffer is marked as changed
  393.  * then we ask if it is ok to blow it away; this is
  394.  * to save the user the grief of losing text. The
  395.  * window chain is nearly always wrong if this gets
  396.  * called; the caller must arrange for the updates
  397.  * that are required. Return TRUE if everything
  398.  * looks good.
  399.  */
  400. bclear(bp) register BUFFER *bp; {
  401.     register LINE    *lp;
  402.     register int    s;
  403.     
  404.     if ((bp->b_flag&BFCHG) != 0        /* Changed.        */
  405.     && (s=eyesno("Buffer modified; kill anyway")) != TRUE)
  406.         return (s);
  407.     bp->b_flag  &= ~BFCHG;            /* Not changed        */
  408.     while ((lp=lforw(bp->b_linep)) != bp->b_linep)
  409.         lfree(lp);
  410.     bp->b_dotp  = bp->b_linep;        /* Fix "."        */
  411.     bp->b_doto  = 0;
  412.     bp->b_markp = NULL;            /* Invalidate "mark"    */
  413.     bp->b_marko = 0;
  414.     return (TRUE);
  415. }
  416.  
  417. /*
  418.  * Display the given buffer in the given window. Flags indicated
  419.  * action on redisplay.
  420.  */
  421. showbuffer(bp, wp, flags) register BUFFER *bp; register WINDOW *wp; {
  422.     register BUFFER    *obp;
  423.     WINDOW        *owp;
  424.  
  425.     if (wp->w_bufp == bp) {            /* Easy case!    */
  426.         wp->w_flag |= flags;
  427.         return TRUE ;
  428.     }
  429.  
  430.     /* First, dettach the old buffer from the window */
  431.     if ((bp->b_altb = obp = wp->w_bufp) != NULL) {
  432.         if (--obp->b_nwnd == 0) {
  433.             obp->b_dotp  = wp->w_dotp;
  434.             obp->b_doto  = wp->w_doto;
  435.             obp->b_markp = wp->w_markp;
  436.             obp->b_marko = wp->w_marko;
  437.         }
  438.     }
  439.  
  440.     /* Now, attach the new buffer to the window */
  441.     wp->w_bufp = bp;
  442.  
  443.     if (bp->b_nwnd++ == 0) {        /* First use.        */
  444.         wp->w_dotp  = bp->b_dotp;
  445.         wp->w_doto  = bp->b_doto;
  446.         wp->w_markp = bp->b_markp;
  447.         wp->w_marko = bp->b_marko;
  448.     } else
  449.     /* already on screen, steal values from other window */
  450.         for (owp = wheadp; owp != NULL; owp = wp->w_wndp)
  451.             if (wp->w_bufp == bp && owp != wp) {
  452.                 wp->w_dotp  = owp->w_dotp;
  453.                 wp->w_doto  = owp->w_doto;
  454.                 wp->w_markp = owp->w_markp;
  455.                 wp->w_marko = owp->w_marko;
  456.                 break;
  457.             }
  458.     wp->w_flag |= WFMODE|flags;
  459.     return TRUE;
  460. }
  461.  
  462. /*
  463.  * Pop the buffer we got passed onto the screen.
  464.  * Returns a status.
  465.  */
  466. WINDOW *
  467. popbuf(bp) register BUFFER *bp; {
  468.     register WINDOW    *wp;
  469.  
  470.     if (bp->b_nwnd == 0) {        /* Not on screen yet.    */
  471.         if ((wp=wpopup()) == NULL) return NULL;
  472.     } else
  473.         for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
  474.             if (wp->w_bufp == bp) {
  475.                 wp->w_flag |= WFHARD|WFFORCE;
  476.                 return wp ;
  477.             }
  478.     if (showbuffer(bp, wp, WFHARD) != TRUE) return NULL;
  479.     return wp;
  480. }
  481.  
  482. /*
  483.  * Insert another buffer at dot.  Very useful.
  484.  */
  485.  
  486. bufferinsert(f, n, k)
  487. {
  488.     register BUFFER *bp;
  489.     register LINE    *clp;
  490.     register int    clo;
  491.     register int    nline;
  492.     int        s;
  493.     char        bufn[NBUFN];
  494.  
  495.     /* Get buffer to use from user */
  496.     if (curbp->b_altb != NULL)
  497.         s=eread("Insert buffer: (default %s) ", bufn, NBUFN,
  498.              EFNEW|EFBUF, &(curbp->b_altb->b_bname),
  499.              (char *) NULL) ;
  500.     else
  501.         s=eread("Insert buffer: ", bufn, NBUFN, EFNEW|EFBUF,
  502.              (char *) NULL) ;
  503.     if (s == ABORT) return (s);
  504.     if (s == FALSE && curbp->b_altb != NULL) bp = curbp->b_altb;
  505.     else if ((bp=bfind(bufn, FALSE)) == NULL) return (FALSE);
  506.  
  507.     if (bp==curbp) {
  508.         ewprintf("Cannot insert buffer into self");
  509.         return (FALSE);
  510.     }
  511.  
  512.     /* insert the buffer */    
  513.     nline = 0;
  514.     for (clp = lforw(bp->b_linep); clp != bp->b_linep; clp = lforw(clp)) {
  515.         for (clo = 0; clo < llength(clp); clo++)
  516.             if (linsert((RSIZE)1, lgetc(clp, clo)) == FALSE)
  517.                 return (FALSE);
  518.         if (newline(FALSE, 1, KRANDOM) == FALSE) /* fake newline */
  519.             return (FALSE);
  520.         nline++;
  521.     }
  522.     if (kbdmop==NULL) {
  523.         if (nline == 1)
  524.             ewprintf("[Inserted 1 line]");
  525.         else
  526.             ewprintf("[Inserted %d lines]", nline);
  527.     }
  528.  
  529.     clp = curwp->w_linep;            /* cosmetic adjustment */
  530.     if (curwp->w_dotp == clp) {        /* for offscreen insert */
  531.         while (nline-- && lback(clp)!=curbp->b_linep)
  532.             clp = lback(clp);
  533.         curwp->w_linep = clp;        /* adjust framing.    */
  534.         curwp->w_flag |= WFHARD;
  535.     }
  536.     return (TRUE);
  537. }
  538.  
  539. /*
  540.  * Turn off the dirty bit on this buffer.
  541.  */
  542. /*ARGSUSED*/
  543. notmodified(f, n, k)
  544. {
  545.     register WINDOW *wp;
  546.     
  547.     curbp->b_flag &= ~BFCHG;
  548.     wp = wheadp;                /* Update mode lines.    */
  549.     while (wp != NULL) {
  550.         if (wp->w_bufp == curbp)
  551.             wp->w_flag |= WFMODE;
  552.         wp = wp->w_wndp;
  553.     }
  554.     ewprintf("Modification-flag cleared");
  555.     return (TRUE);
  556. }
  557.